-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
--
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local log = require 'mc.logging'
local utils_file = require 'utils.file'
local utils_core = require 'utils.core'
local utils_vos = require 'utils.vos'
local cjson = require 'cjson'

local m = {}

local function get_file_content(path)
    if not utils_core.is_file(path) then
        return
    end

    local file = utils_file.open_s(path, 'r')
    if not file then
        log:debug('Open file failed')
        return nil
    end
    local content = file:read('*a')
    file:close()
    return content
end

local function get_bios_object(mdb, bus, systemid)
    local path = '/bmc/kepler/Systems/' .. tostring(systemid) .. '/Bios'
    local interface = 'bmc.kepler.Systems.Bios'
    local ok, bios_obj = pcall(function ()
        return mdb.get_object(bus, path, interface)
    end)
    if not ok then
        log:debug('Get current value file failed, ret = %s', bios_obj)
        return nil
    end

    return bios_obj
end

function m.get_attributes(systemid)
    local bios_obj = get_bios_object(mdb, bus, systemid)
    if bios_obj == nil then
        log:debug('Get attributes failed')
        return nil
    end

    local content = get_file_content(bios_obj.CurrentValueFileName)
    return cjson.json_object_ordered_decode(content)
end

function m.get_time()
    local path = '/bmc/kepler/Managers/Time_Bmc_000101'
    local interface = 'bmc.kepler.Managers.Time'
    local date_time
    local ok, ret = pcall(function ()
        local obj = mdb.get_object(bus, path, interface)
        date_time = obj.DateTime
    end)
    if not ok then
        log:info('Get date time failed, ret = %s', ret)
        return nil
    end

    return date_time
end

function m.get_etag(systemid)
    local bios_obj = get_bios_object(mdb, bus, systemid)
    if bios_obj == nil then
        log:debug('Get etag failed')
        return nil
    end

    local content = get_file_content(bios_obj.CurrentValueFileName)
    local sha256sum = utils_vos.compute_checksum(utils_vos.G_CHECKSUM_SHA256, content)
    -- 截取校验和的1-8字节作为etag
    return sha256sum:sub(1, 8)
end

function m.get_setting_attributes(systemid)
    local bios_obj = get_bios_object(mdb, bus, systemid)
    if bios_obj == nil then
        log:debug('Get attributes failed')
        return nil
    end

    local content = get_file_content(bios_obj.SettingFileName)
    return cjson.json_object_ordered_decode(content)
end

function m.encode_attributes(attributes)
    local data = cjson.json_object_new_object()
    data['Attributes'] = attributes
    return attributes ~= nil and cjson.json_object_ordered_encode(data) or nil
end

function m.get_registry_version(systemid)
    local bios_obj = get_bios_object(mdb, bus, systemid)
    if bios_obj == nil or bios_obj.RegistryVersion == '' then
        log:debug('Get bios registry version failed')
        return nil
    end
    -- 格式转换：V1.00 -> BiosAttributeRegistry.1.0.0
    local first, second, third = string.match(bios_obj.RegistryVersion, 'V(%d)%.(%d)(%d)')
    local registry_version = 'BiosAttributeRegistry.' .. first .. '.' .. second .. '.' .. third
    return registry_version
end

function m.get_messages(systemid)
    local bios_obj = get_bios_object(mdb, bus, systemid)
    if bios_obj == nil then
        log:debug('Get bios registry version failed')
        return nil
    end
    local content = cjson.decode(get_file_content(bios_obj.ResultFileName))
    return content['Messages']
end

function m.get_certificates(cert_info_seq, cert_info)
    local obj = {}
    local cert_info_seq = cjson.decode(cert_info_seq)
    obj['SecureBoot'] = cert_info_seq['SecureBoot']
    local cert_info = cjson.decode(cert_info)
    obj['Boot'] = cert_info['Boot']
    if not obj.SecureBoot and not obj.Boot then
        obj = cjson.null
    end
    return obj
end
function m.get_boot_cert(cert_info)
    local cert_info = cjson.decode(cert_info)
    return cert_info['Boot']
end

function m.get_secureboot_cert(cert_info)
    local cert_info = cjson.decode(cert_info)
    return cert_info['SecureBoot']
end

function m.get_active_software_image(systemid)
    local obj = cjson.json_object_new_object()
    if systemid == '1' then
        obj["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory/Bios"
    else
        obj["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory/Bios" .. systemid
    end
    return obj
end

return m
